import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Panel;
import java.awt.Scrollbar;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;

import javax.swing.Timer;

/**
 * 
 */
/**
 * @author Darth Android
 * @date Oct 4, 2007
 */
public class LCDPanel extends Panel implements ActionListener {

	private static Color[] COLOR_LIST = new Color[256];
	static {
		for (int i = 0; i < 256; i++) {
			COLOR_LIST[i] = new Color(i, i, i);
		}
	}

	/**
	 * @param i
	 * @param j
	 */
	public LCDPanel(int width, int height) {
		this.width = width;
		this.height = height;
		setBackground(Color.WHITE);
		display = new int[width][height];
		buffer = new boolean[width][height];
		timer = new Timer(refreshRate / 1000, this);
		timer.start();
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Frame frame = new Frame("LCD Test");
		frame.setSize(96 * 5 + 95, 64 * 5 + 63);
		frame.setVisible(true);
		frame.setLayout(new BorderLayout());
		final LCDPanel lcd = new LCDPanel(96, 64);
		frame.add(lcd);
		lcd.setPixel(0, 0, false);
		final Timer t = new Timer(1000 / 200, new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				for (int x = 0; x < 6; x++)
					for (int y = 0; y < 8; y++)
						lcd.setPixel(x, y, !lcd.getPixel(x, y));
			}
		});
		t.start();
		Scrollbar refreshSB = new Scrollbar(Scrollbar.VERTICAL, 200, 10, 0, 1000);
		frame.add(refreshSB, BorderLayout.WEST);
		refreshSB.addAdjustmentListener(new AdjustmentListener() {

			public void adjustmentValueChanged(AdjustmentEvent e) {
				t.setDelay(e.getValue());
			}
		});
		Scrollbar updateSB = new Scrollbar(Scrollbar.VERTICAL, 50, 10, 0, 1000);
		frame.add(updateSB, BorderLayout.EAST);
		updateSB.addAdjustmentListener(new AdjustmentListener() {

			public void adjustmentValueChanged(AdjustmentEvent e) {
				lcd.setRefreshRate(e.getValue());
			}
		});
	}

	private int width;
	private int height;
	private int[][] display;
	private boolean[][] buffer;
	private int refreshRate = 50;
	private int updateSpeed = 255;
	private Timer timer;

	@Override
	public void paint(Graphics g) {
		super.paint(g);
		paintPxls(g);
	}

	public void paintPxls(Graphics g) {
		int pxlWidth = (int) (getWidth() / (double) width);
		int pxlHeight = (int) (getHeight() / (double) height);
		for (int y = 0; y < height; y++) {
			for (int x = 0; x < width; x++) {
				g.setColor(COLOR_LIST[display[x][y]]);
				g.fillRect((int) (pxlWidth * x), (int) (pxlHeight * y), (int) pxlWidth - 1, (int) pxlHeight - 1);
			}
		}
	}

	public void actionPerformed(ActionEvent e) {
		for (int y = 0; y < height; y++) {
			for (int x = 0; x < width; x++) {
				int pxl = display[x][y];
				pxl += updateSpeed * (buffer[x][y] ? -1 : 1);
				if (pxl < 0)
					pxl = 0;
				if (pxl > 255)
					pxl = 255;
				display[x][y] = pxl;
			}
		}
		paintPxls(getGraphics());
	}

	public void setPixel(int x, int y, boolean black) {
		buffer[x][y] = black;
	}

	public boolean getPixel(int x, int y) {
		return buffer[x][y];
	}

	public void setRefreshRate(int rate) {
		refreshRate = rate;
	}
}
